/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.net; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; /*** * The DatagramSocketClient provides the basic operations that are required * of client objects accessing datagram sockets. It is meant to be * subclassed to avoid having to rewrite the same code over and over again * to open a socket, close a socket, set timeouts, etc. Of special note * is the {@link #setDatagramSocketFactory setDatagramSocketFactory } * method, which allows you to control the type of DatagramSocket the * DatagramSocketClient creates for network communications. This is * especially useful for adding things like proxy support as well as better * support for applets. For * example, you could create a * {@link org.apache.commons.net.DatagramSocketFactory} * that * requests browser security capabilities before creating a socket. * All classes derived from DatagramSocketClient should use the * {@link #_socketFactory_ _socketFactory_ } member variable to * create DatagramSocket instances rather than instantiating * them by directly invoking a constructor. By honoring this contract * you guarantee that a user will always be able to provide his own * Socket implementations by substituting his own SocketFactory. * <p> * <p> * @author Daniel F. Savarese * @see DatagramSocketFactory ***/ public abstract class DatagramSocketClient { /*** * The default DatagramSocketFactory shared by all DatagramSocketClient * instances. ***/ private static final DatagramSocketFactory __DEFAULT_SOCKET_FACTORY = new DefaultDatagramSocketFactory(); /*** The timeout to use after opening a socket. ***/ protected int _timeout_; /*** The datagram socket used for the connection. ***/ protected DatagramSocket _socket_; /*** * A status variable indicating if the client's socket is currently open. ***/ protected boolean _isOpen_; /*** The datagram socket's DatagramSocketFactory. ***/ protected DatagramSocketFactory _socketFactory_; /*** * Default constructor for DatagramSocketClient. Initializes * _socket_ to null, _timeout_ to 0, and _isOpen_ to false. ***/ public DatagramSocketClient() { _socket_ = null; _timeout_ = 0; _isOpen_ = false; _socketFactory_ = __DEFAULT_SOCKET_FACTORY; } /*** * Opens a DatagramSocket on the local host at the first available port. * Also sets the timeout on the socket to the default timeout set * by {@link #setDefaultTimeout setDefaultTimeout() }. * <p> * _isOpen_ is set to true after calling this method and _socket_ * is set to the newly opened socket. * <p> * @exception SocketException If the socket could not be opened or the * timeout could not be set. ***/ public void open() throws SocketException { _socket_ = _socketFactory_.createDatagramSocket(); _socket_.setSoTimeout(_timeout_); _isOpen_ = true; } /*** * Opens a DatagramSocket on the local host at a specified port. * Also sets the timeout on the socket to the default timeout set * by {@link #setDefaultTimeout setDefaultTimeout() }. * <p> * _isOpen_ is set to true after calling this method and _socket_ * is set to the newly opened socket. * <p> * @param port The port to use for the socket. * @exception SocketException If the socket could not be opened or the * timeout could not be set. ***/ public void open(int port) throws SocketException { _socket_ = _socketFactory_.createDatagramSocket(port); _socket_.setSoTimeout(_timeout_); _isOpen_ = true; } /*** * Opens a DatagramSocket at the specified address on the local host * at a specified port. * Also sets the timeout on the socket to the default timeout set * by {@link #setDefaultTimeout setDefaultTimeout() }. * <p> * _isOpen_ is set to true after calling this method and _socket_ * is set to the newly opened socket. * <p> * @param port The port to use for the socket. * @param laddr The local address to use. * @exception SocketException If the socket could not be opened or the * timeout could not be set. ***/ public void open(int port, InetAddress laddr) throws SocketException { _socket_ = _socketFactory_.createDatagramSocket(port, laddr); _socket_.setSoTimeout(_timeout_); _isOpen_ = true; } /*** * Closes the DatagramSocket used for the connection. * You should call this method after you've finished using the class * instance and also before you call {@link #open open() } * again. _isOpen_ is set to false and _socket_ is set to null. * If you call this method when the client socket is not open, * a NullPointerException is thrown. ***/ public void close() { _socket_.close(); _socket_ = null; _isOpen_ = false; } /*** * Returns true if the client has a currently open socket. * <p> * @return True if the client has a curerntly open socket, false otherwise. ***/ public boolean isOpen() { return _isOpen_; } /*** * Set the default timeout in milliseconds to use when opening a socket. * After a call to open, the timeout for the socket is set using this value. * This method should be used prior to a call to {@link #open open()} * and should not be confused with {@link #setSoTimeout setSoTimeout()} * which operates on the currently open socket. _timeout_ contains * the new timeout value. * <p> * @param timeout The timeout in milliseconds to use for the datagram socket * connection. ***/ public void setDefaultTimeout(int timeout) { _timeout_ = timeout; } /*** * Returns the default timeout in milliseconds that is used when * opening a socket. * <p> * @return The default timeout in milliseconds that is used when * opening a socket. ***/ public int getDefaultTimeout() { return _timeout_; } /*** * Set the timeout in milliseconds of a currently open connection. * Only call this method after a connection has been opened * by {@link #open open()}. * <p> * @param timeout The timeout in milliseconds to use for the currently * open datagram socket connection. ***/ public void setSoTimeout(int timeout) throws SocketException { _socket_.setSoTimeout(timeout); } /*** * Returns the timeout in milliseconds of the currently opened socket. * If you call this method when the client socket is not open, * a NullPointerException is thrown. * <p> * @return The timeout in milliseconds of the currently opened socket. ***/ public int getSoTimeout() throws SocketException { return _socket_.getSoTimeout(); } /*** * Returns the port number of the open socket on the local host used * for the connection. If you call this method when the client socket * is not open, a NullPointerException is thrown. * <p> * @return The port number of the open socket on the local host used * for the connection. ***/ public int getLocalPort() { return _socket_.getLocalPort(); } /*** * Returns the local address to which the client's socket is bound. * If you call this method when the client socket is not open, a * NullPointerException is thrown. * <p> * @return The local address to which the client's socket is bound. ***/ public InetAddress getLocalAddress() { return _socket_.getLocalAddress(); } /*** * Sets the DatagramSocketFactory used by the DatagramSocketClient * to open DatagramSockets. If the factory value is null, then a default * factory is used (only do this to reset the factory after having * previously altered it). * <p> * @param factory The new DatagramSocketFactory the DatagramSocketClient * should use. ***/ public void setDatagramSocketFactory(DatagramSocketFactory factory) { if (factory == null) _socketFactory_ = __DEFAULT_SOCKET_FACTORY; else _socketFactory_ = factory; } }